/*
async 函数的实现原理， 就是将 Generator 函数和自动执行器， 包装在一个函数里。
所有的async函数都可以写成第二种形式，其中的spawn函数就是自动执行器。
*/

async function fn(args) {
	// 你的业务代码
}

// 等同于

function fn(args) {
	return spawn(function*() { //    /spɔːn/ 
		// 你的业务代码
	});
}

//下面给出spawn函数的实现，基本就是前文自动执行器的翻版。co thunk的自动执行

function spawn(genF) {
	return new Promise(function(resolve, reject) {
		const gen = genF();

		function step(nextF) {
			let next;
			try {
				next = nextF();
			} catch (e) {
				return reject(e);
			}
			if (next.done) {
				return resolve(next.value);
			}
			Promise.resolve(next.value).then(function(v) {
				step(function() {
					return gen.next(v);
				});
			}, function(e) {
				step(function() {
					return gen.throw(e);
				});
			});
		}
		step(function() {
			return gen.next(undefined);
		});
	});
}
